// ==============================================================================================
// BSD 3-Clause Clear License
// Copyright © 2025 ZAMA. All rights reserved.
// ----------------------------------------------------------------------------------------------
// Header and constants used by ucore firmware
// ==============================================================================================

#include "pll.h"
#include "hpu_dop_fmt.h"
#include "hpu_iop_fmt.h"

// Headers
// ============================================================================================= //
#include <stdio.h>

// Constants
// ============================================================================================= //
#define UCORE_VERSION_MAJOR              (2)
#define UCORE_VERSION_MINOR              (0)

#define OFFSET_TO_AMI_IOPACKQ_HEAD       (0x200000)
#define OFFSET_TO_AMI_IOPACKQ_DATA_START (0x200004)
#define OFFSET_TO_AMI_IOPACKQ_TAIL       (0x210004)
#define AMI_IOPACKQ_MAX_WORDS            (0x4000)

#define OFFSET_FROM_AMI_IOPQ_HEAD        (0x7000000)
#define OFFSET_FROM_AMI_IOPQ_DATA_START  (0x7000004)
#define OFFSET_FROM_AMI_IOPQ_TAIL        (0x7020000)
#define AMI_IOPQ_MAX_BYTES               (0x10000)

#define DOP_LUT_ADDR  ((size_t) 0x39000000)
// Opcode is 8bit -> 256 words entry per blk_w
#define DOP_LUT_RANGE ((size_t) 0x100)
#define SYNC_DOP_WORD 0x4000ffff

// WARN seems to have limitation on isc_write
#define DOP_BUFFER_LOG2_SIZE 8
#define DOP_BUFFER_SIZE (1 << DOP_BUFFER_LOG2_SIZE)

// Local Ack -> IOp lookup
#define ACK_IOP_DEPTH 256



// Type
// ============================================================================================= //
// Lookup entry
typedef struct {
  volatile uint32_t* ptr;
  size_t len;
} Lookup_t;

// Local Ack -> IOp lookup
// Use to store match between received ack and corresponding IOp
typedef struct {
  uint32_t iop[ACK_IOP_DEPTH];
  size_t wr_idx;
  size_t rd_idx;
} AckIopLut_t;

// Hpu functions prototypes
// ============================================================================================= //
uint32_t parse_iop(
     uint32_t *stream,
     uint32_t iop_pending_bytes,
     // Static allocated buffer used during IOp parsing
     IOpHeader_t *header,
     IOpOperand_t *operand,
     IOpImmHeader_t *imm_header,
     // Operand/Immediat bundle generated by the parser
     OperandBundle_t* dst,
     OperandBundle_t* src,
     ImmediatBundle_t* imm);
uint32_t get_lookup(IOpHeader_t header, Lookup_t* lookup);
void patch_mem_dop(DOpu_t *dop, OperandBundle_t *iop_dst, OperandBundle_t *iop_src);
void patch_imm_dop(DOpu_t *dop, ImmediatBundle_t *iop_imm);
void patch_dop(DOpu_t *dop,
               OperandBundle_t *dst,
               OperandBundle_t *src,
               ImmediatBundle_t *imm);
DOpKind_t get_kind(DOpu_t *dop);

